package com.zhentao.controller;

import com.zhentao.service.ParamCacheService;
import com.zhentao.util.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 仪表板数据控制器
 * 为前端提供概览数据
 *
 * @author zhentao
 * @since 2024-08-28
 */
@Tag(name = "仪表板数据", description = "系统概览数据接口")
@RestController
@RequestMapping("/dashboard")
@Slf4j
@RequiredArgsConstructor
public class DashboardController {

    private final JdbcTemplate jdbcTemplate;
    private final ParamCacheService paramCacheService;
    private final RedisConnectionFactory redisConnectionFactory;

    /**
     * 获取系统统计数据
     */
    @Operation(summary = "获取系统统计数据", description = "返回系统基本统计信息")
    @GetMapping("/stats")
    public Result getSystemStats() {
        try {
            Map<String, Object> stats = new HashMap<>();
            stats.put("totalParams", count("param_definition"));
            stats.put("dataRecords", count("param_value") + count("param_metrics"));
            stats.put("anomalies", safeCount("anomaly_monitor_result"));
            stats.put("activeUsers", safeCount("sys_user"));
            return Result.OK(stats);
        } catch (Exception e) {
            log.error("获取系统统计数据失败", e);
            return Result.ERROR("获取系统统计数据失败");
        }
    }

    private long count(String table) {
        return jdbcTemplate.queryForObject("SELECT COUNT(*) FROM " + table, Long.class);
    }

    private long safeCount(String table) {
        try {
            return count(table);
        } catch (Exception e) {
            return 0L;
        }
    }

    /**
     * 获取系统状态
     */
    @Operation(summary = "获取系统状态", description = "返回各模块运行状态")
    @GetMapping("/status")
    public Result getSystemStatus() {
        try {
            return Result.OK(Collections.emptyList());
        } catch (Exception e) {
            log.error("获取系统状态失败", e);
            return Result.ERROR("获取系统状态失败");
        }
    }

    /**
     * 获取 Redis 实时指标
     */
    @Operation(summary = "获取Redis指标", description = "返回缓存命中率、键数量、最近更新时间等")
    @GetMapping("/redis")
    public Result getRedisStats() {
        try {
            Map<String, Object> resp = new HashMap<>();

            // 1) 从业务统计中取命中率
            Map<String, Object> stats = paramCacheService.getCacheStatistics();
            resp.put("definitionHitRate", stats.getOrDefault("definition_hit_rate", "0%"));
            resp.put("valueHitRate", stats.getOrDefault("value_hit_rate", "0%"));
            resp.put("lastUpdate", stats.get("last_update"));

            // 2) 读取 Redis INFO 获取内存与key数量
            RedisConnection connection = null;
            try {
                connection = redisConnectionFactory.getConnection();
                Properties memoryInfo = connection.info("memory");
                Properties statsInfo = connection.info("stats");
                Properties keyspaceInfo = connection.info("keyspace");

                long usedMemory = parseLong(memoryInfo, "used_memory");
                long maxMemory = parseLong(memoryInfo, "maxmemory");
                Double usagePercent = null;
                if (maxMemory > 0) {
                    usagePercent = (usedMemory * 100.0) / maxMemory;
                }

                long hits = parseLong(statsInfo, "keyspace_hits");
                long misses = parseLong(statsInfo, "keyspace_misses");
                if ((hits + misses) > 0) {
                    double rate = (hits * 100.0) / (hits + misses);
                    // 若业务统计无值，则使用Redis原生统计
                    resp.putIfAbsent("valueHitRate", String.format("%.2f%%", rate));
                }

                // 提取 db0 键数量（形式如：db0:keys=123,expires=10,avg_ttl=0）
                String db0 = keyspaceInfo.getProperty("db0");
                if (db0 != null) {
                    int keysIdx = db0.indexOf("keys=");
                    if (keysIdx >= 0) {
                        String sub = db0.substring(keysIdx + 5);
                        int comma = sub.indexOf(',');
                        String keysStr = comma > -1 ? sub.substring(0, comma) : sub;
                        resp.put("keys", Long.parseLong(keysStr));
                    }
                }

                resp.put("usedMemory", usedMemory);
                resp.put("maxMemory", maxMemory);
                if (usagePercent != null) {
                    resp.put("usagePercent", String.format("%.2f%%", usagePercent));
                }
            } finally {
                if (connection != null) {
                    try { connection.close(); } catch (Exception ignore) {}
                }
            }

            return Result.OK(resp);
        } catch (Exception e) {
            log.error("获取Redis指标失败", e);
            return Result.ERROR("获取Redis指标失败");
        }
    }

    private long parseLong(Properties props, String key) {
        if (props == null) return 0L;
        String v = props.getProperty(key);
        if (v == null) return 0L;
        try { return Long.parseLong(v); } catch (Exception ignored) { return 0L; }
    }

    /**
     * 获取最近活动
     */
    @Operation(summary = "获取最近活动", description = "返回最近的系统活动记录")
    @GetMapping("/activities")
    public Result getRecentActivities() {
        try {
            return Result.OK(Collections.emptyList());
        } catch (Exception e) {
            log.error("获取最近活动失败", e);
            return Result.ERROR("获取最近活动失败");
        }
    }

    /**
     * 获取参数引擎统计数据
     */
    @Operation(summary = "获取参数引擎统计", description = "返回参数引擎相关统计数据")
    @GetMapping("/param-engine/stats")
    public Result getParamEngineStats() {
        try {
            Map<String, Object> stats = new HashMap<>();
            stats.put("categories", count("param_category"));
            stats.put("definitions", count("param_definition"));
            stats.put("rules", count("param_rule"));
            stats.put("recommendations", count("param_recommendation"));
            return Result.OK(stats);
        } catch (Exception e) {
            log.error("获取参数引擎统计数据失败", e);
            return Result.ERROR("获取参数引擎统计数据失败");
        }
    }

    /**
     * 获取健康检查
     */
    @Operation(summary = "健康检查", description = "检查系统健康状态")
    @GetMapping("/health")
    public Result healthCheck() {
        try {
            Map<String, Object> health = new HashMap<>();
            health.put("status", "UP");
            health.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            health.put("version", "1.0.0");
            health.put("uptime", "15天8小时32分钟");
            
            return Result.OK(health);
        } catch (Exception e) {
            log.error("健康检查失败", e);
            return Result.ERROR("健康检查失败");
        }
    }
}


